package com.crux.ribbon;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.DefaultResponse;
import org.springframework.cloud.client.loadbalancer.EmptyResponse;
import org.springframework.cloud.client.loadbalancer.Request;
import org.springframework.cloud.client.loadbalancer.Response;
import org.springframework.cloud.loadbalancer.core.ReactorServiceInstanceLoadBalancer;
import org.springframework.cloud.loadbalancer.core.SelectedInstanceCallback;
import org.springframework.cloud.loadbalancer.core.ServiceInstanceListSupplier;
import reactor.core.publisher.Mono;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

@Slf4j
public class EurekaLoadBalancer implements ReactorServiceInstanceLoadBalancer {
    //private static final Logger logger = LoggerFactory.getLogger(EurekaLoadBalancer.class);

    private final String serviceId;
    private ServiceInstanceListSupplier supplier;

    public EurekaLoadBalancer(String serviceId, ServiceInstanceListSupplier supplier) {
        this.serviceId = serviceId;
        this.supplier = supplier;
    }

    @Override
    public Mono<Response<ServiceInstance>> choose(Request request) {
        return supplier.get(request).next().map(this::processResponse);
    }

    private Response<ServiceInstance> processResponse(List<ServiceInstance> serviceInstances) {
        //List<ServiceInstance> serviceInstances2 = filteredByZone(serviceInstances);
        Response<ServiceInstance> serviceInstanceResponse = this.getInstanceResponse(serviceInstances);
        if (supplier instanceof SelectedInstanceCallback && serviceInstanceResponse.hasServer()) {
            ((SelectedInstanceCallback) supplier).selectedServiceInstance(serviceInstanceResponse.getServer());
        }
        return serviceInstanceResponse;
    }

    private Response<ServiceInstance> getInstanceResponse(List<ServiceInstance> instances) {
        if (instances.isEmpty()) {
            log.error("{}没有对应的服务实例", this.serviceId);
            return new EmptyResponse();
        } else {
            //获取请求对象
            int index = ThreadLocalRandom.current().nextInt(instances.size());
            ServiceInstance instance = (ServiceInstance) instances.get(index);
            return new DefaultResponse(instance);
        }
    }
}
